#ifndef _BUFFER_H_
#define _BUFFER_H_

#include "def.h"

#ifdef __cplusplus
extern "C"{
#endif

struct buffer
{
    uint8_t *orig_buf;
    size_t size;
    size_t min_size;
    size_t off;
    size_t misalign;
};

typedef struct buffer buffer_t;

inline static size_t buffer_size(buffer_t *self)
{
    return self->size;
}

inline static size_t buffer_len(buffer_t *self)
{
    return self->off - self->misalign;
}

inline static uint8_t *buffer_data(buffer_t *self)
{
    if(buffer_len(self) == 0)
        return NULL;

    return self->orig_buf + self->misalign;
}

inline static uint8_t *buffer_space(buffer_t *self)
{
    return self->orig_buf + self->off;
}

inline static void buffer_off_inc(buffer_t *self, size_t len)
{
    if(self)
        self->off += len;
}

int buffer_init(buffer_t *self, size_t size);
void buffer_term(buffer_t *self);
buffer_t *buffer_new(size_t size);
void buffer_destroy(buffer_t **p_self);


int buffer_drain(buffer_t *self, size_t len);
int buffer_expand(buffer_t *self, size_t len);
int buffer_clean(buffer_t *self);
int buffer_reset(buffer_t *self);


int buffer_add(buffer_t *self, void *data, size_t len);
int buffer_add_buffer(buffer_t *self, buffer_t *buf);
int buffer_snprintf(buffer_t *self, const char *fmt, ...);
int buffer_get(buffer_t *self, void *data, size_t size);
uint8_t *buffer_getline(buffer_t *self, size_t *got_len);


int buffer_from_fd(buffer_t *self, int fd, size_t size);
int buffer_to_fd(buffer_t *self, int fd, size_t size);


#ifdef __cplusplus
}
#endif

#endif
